package com.lmbsvn.front.shiro.config;

import com.lmbsvn.core.shiro.credential.LimitRetryHashedMatcher;
import com.lmbsvn.core.shiro.filter.MyFormAuthenticationFilter;
import com.lmbsvn.front.shiro.realm.ShiroRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro 前台配置
 * @author lumingbao
 * @version 1.0
 */
@Configuration
public class ShiroConfig {

	/**
	 * 缓存管理器 使用Redis实现
	 * @return
	 */
	@Bean(name = "ShiroCacheManager")
    public EhCacheManager getEhCacheManager() {
		EhCacheManager manager = new EhCacheManager();
		manager.setCacheManagerConfigFile("classpath:conf/ehcache.xml");
		return manager;
    }

	/**
	 * 凭证匹配器
	 * @return
	 */
	@Bean(name = "credentialsMatcher")
	public LimitRetryHashedMatcher getLimitRetryHashedMatcher() {
		LimitRetryHashedMatcher credentialsMatcher = new LimitRetryHashedMatcher(getEhCacheManager());
		//指定hash算法为MD5
		credentialsMatcher.setHashAlgorithmName("md5");
		//指定散列次数为2次
		credentialsMatcher.setHashIterations(2);
		//指定Hash散列值使用Hex加密存储
		credentialsMatcher.setStoredCredentialsHexEncoded(true);
		return credentialsMatcher;
	}

	/**
	 * Realm实现
	 * @return
	 */
	@Bean(name = "myRealm")
    public ShiroRealm getShiroRealm() {
		ShiroRealm realm = new ShiroRealm();
		//密码校验接口
		realm.setCachingEnabled(true);
		realm.setAuthenticationCachingEnabled(false);
		realm.setAuthenticationCacheName("authenticationCache");
		realm.setAuthorizationCachingEnabled(true);
		realm.setAuthorizationCacheName("authorizationCache");
		realm.setCredentialsMatcher(getLimitRetryHashedMatcher());
        return realm;
    }

	/**
	 * 记住我Cookie模板
	 * @return
	 */
	@Bean(name = "rememberMeCookie")
	public SimpleCookie getRememberMeCookie() {
		SimpleCookie cookie = new SimpleCookie("rememberMe");
		cookie.setHttpOnly(true);
		cookie.setMaxAge(2592000);//30天
		return cookie;
	}

	/**
	 * rememberMe管理器
	 * @return
	 */
	@Bean(name = "rememberMeManager")
	public CookieRememberMeManager getCookieRememberMeManager() {
		CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
		rememberMeManager.setCipherKey(org.apache.shiro.codec.Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
		rememberMeManager.setCookie(getRememberMeCookie());
		return rememberMeManager;
	}

	/**
	 * 安全管理器
	 * @return
	 */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(getShiroRealm());
        securityManager.setCacheManager(getEhCacheManager());
        securityManager.setRememberMeManager(getCookieRememberMeManager());
        return securityManager;
    }

    /**
     * logout过滤器
     * @return
     */
    public LogoutFilter getLogoutFilter() {
    	LogoutFilter logoutFilter = new LogoutFilter();
    	logoutFilter.setRedirectUrl("/logout.do");
        return logoutFilter;
    }

    /**
     * 重写 FormAuthenticationFilter
     * @return
     */
    public MyFormAuthenticationFilter getMyFormAuthenticationFilter() {
        return new MyFormAuthenticationFilter();
    }

	@Bean
	public FilterRegistrationBean filterRegistrationBean() {
		FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
		filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
		//  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
		filterRegistration.addInitParameter("targetFilterLifecycle", "true");
		filterRegistration.setEnabled(true);
		filterRegistration.addUrlPatterns("/*");// 可以自己灵活的定义很多，避免一些根本不需要被Shiro处理的请求被包含进来
		return filterRegistration;
	}

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
    	Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
        shiroFilterFactoryBean.setLoginUrl("/login.htm");//要求登录时的链接
        shiroFilterFactoryBean.setSuccessUrl("/index.htm");//登录成功后要跳转的连接
        shiroFilterFactoryBean.setUnauthorizedUrl("/");//用户访问未对其授权的资源时,所显示的连接


		filterChainDefinitionMap.put("/resources/**", "anon");
		filterChainDefinitionMap.put("/captcha/**", "anon");
		filterChainDefinitionMap.put("/login.htm", "anon");
		filterChainDefinitionMap.put("/login.do", "anon");
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/**", "authc");

		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        shiroFilterFactoryBean.setFilters(getFilters());
        return shiroFilterFactoryBean;
    }

    public Map<String, Filter> getFilters(){
		Map<String, Filter> filters = new HashMap();
		filters.put("logout", getLogoutFilter());
		filters.put("authc", getMyFormAuthenticationFilter());
    	return filters;
    }
}
